package ebedynky.services;

import ebedynky.beans.HibernateUtil;
import ebedynky.beans.Administrator;
import ebedynky.beans.Message;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 * @author davidon1
 */
public class AdministratorService {

    /**
     * Seesion - current connection to the db.
     */
    private Session session;

    /**
     * Constructor, retrieves the session (connection).
     */
    public AdministratorService() {
        this.session = HibernateUtil.getSessionFactory().openSession();
    }

    /**
     * Closes the session (connection).
     * @return success/failure.
     */
    public boolean close() {
        this.session.close();
        return !(this.session.isOpen());
    }

    /**
     * Restarts the session (connection).
     * @return success/failure.
     */
    public boolean restart() {
        this.session.close();
        if (this.session.isOpen()) {
            throw new IllegalStateException("Session could not be closed.");
        }
        this.session = HibernateUtil.getSessionFactory().openSession();
        return this.session.isOpen();
    }

    /**
     * Adds Administrator to the db.
     * @param admin Administrator to be inserted
     * @return ID of the added Administrator
     */
    public int addAdministrator(Administrator admin) {
        session.beginTransaction();
        int id = getMaxAdministratorID() + 1;
        admin.setAdministratorID(id);
        id = (Integer)  session.save(admin);
        session.getTransaction().commit();
        return (id);
    }

    /**
     * Retrieves the maximum id currently in the database of Administrators.
     * @return Max ID
     */
    public int getMaxAdministratorID() {
        String hql = "select max(u.userID) from User u";
        List list = session.createQuery(hql).list();
        if (list.get(0) != null) {
            Integer maxadminid = (Integer) list.get(0);
            return maxadminid;
        } else {
            return 0;
        }
    }

    /**
     * Retrieves a Administrator identified by the ID.
     * @param id of the Administrator
     * @return Administrator with the ID given (null if not found)
     */
    public Administrator getAdministratorByID(int id) {
        session.beginTransaction();
        Administrator admin = (Administrator) session.get(Administrator.class, new Integer(id));
        session.getTransaction().commit();
        return (admin);
    }

    /**
     * Retrieves a list of all Administrators stored in the db.
     * @return List of all Administrators (null if no Administrators)
     */
    public List<Administrator> getAllAdministrators() {
        session.beginTransaction();
        List<Administrator> adminList = session.createQuery("from Administrator").list();
        session.getTransaction().commit();
        return (adminList);
    }

    /**
     * Updates a specified Administrator identified by ID.
     * @param newAdministrator an updated Administrator
     */
    public void updateAdministrator(Administrator newAdministrator) {
        session.beginTransaction();
        Administrator admin = (Administrator) session.get(Administrator.class, new Integer(newAdministrator.getUserID()));
        admin.setAccountState(newAdministrator.getAccountState());
        admin.setRoles(newAdministrator.getRoles());
        admin.setStreet(newAdministrator.getStreet());
        admin.setStreetNo(newAdministrator.getStreetNo());
        admin.setCity(newAdministrator.getCity());
        admin.setZip(newAdministrator.getZip());
        admin.setEmail(newAdministrator.getEmail());
        admin.setFroms(newAdministrator.getFroms());
        admin.setName(newAdministrator.getName());
        admin.setPass(newAdministrator.getPass());
        admin.setSurname(newAdministrator.getSurname());
        admin.setTos(newAdministrator.getTos());
        admin.setUsername(newAdministrator.getUsername());
        session.flush();
        session.getTransaction().commit();
        session.clear();
    }

    /**
     * Removes the Administrator from db.
     * @param id Administrator ID for removal
     * @return true if successful, false otherwise
     */
    public boolean deleteAdministrator(int id) {
        try {
            session.beginTransaction();
            Administrator admin = (Administrator) session.get(Administrator.class, new Integer(id));
            session.delete(admin);
            session.getTransaction().commit();
            return (true);
        } catch (HibernateException ex) {
            return (false);
        }
    }

    /**
     * Returns all messages that were aimed to this admin.
     * @param admin for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getToMessages(Administrator admin) {
        if (admin == null || admin.getTos() == null || admin.getTos().isEmpty())
            return new ArrayList<Message>(0);
        return new ArrayList<Message>(admin.getTos());
    }

    /**
     * Returns all messages that were aimed to this admin.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getToMessages(int id) {
        return getToMessages(getAdministratorByID(id));
    }

    /**
     * Returns all messages that were aimed from this admin.
     * @param admin for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getFromMessages(Administrator admin) {
        if (admin == null || admin.getFroms() == null || admin.getFroms().isEmpty())
            return new ArrayList<Message>(0);
        return new ArrayList<Message>(admin.getFroms());
    }

    /**
     * Returns all messages that were aimed from this admin.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getFromMessages(int id) {
        return getFromMessages(getAdministratorByID(id));
    }

    /**
     * Returns all messages that were aimed to/from this admin.
     * @param admin for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllMessages(Administrator admin) {
        if (admin == null || admin.getTos() == null || admin.getTos().isEmpty())
            return new ArrayList<Message>(0);
        ArrayList<Message> am = new ArrayList<Message>(admin.getTos());
        if (admin.getFroms() != null && !admin.getFroms().isEmpty())
            am.addAll(admin.getFroms());
        return am;
    }

    /**
     * Returns all messages that were aimed to/from this admin.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllMessages(int id) {
        return getAllMessages(getAdministratorByID(id));
    }

    /**
     * Returns all unread messages that were aimed to this admin.
     * @param admin for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllUnreadMessages(Administrator admin) {
        if (admin == null || admin.getTos() == null || admin.getTos().isEmpty())
            return new ArrayList<Message>(0);
        ArrayList<Message> am = new ArrayList<Message>(admin.getTos());
        for (Message m : am)
            if (!m.isUnread())
                am.remove(m);
        return am;
    }

    /**
     * Returns all unread messages that were aimed to this admin.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllUnreadMessages(int id) {
        return getAllUnreadMessages(getAdministratorByID(id));
    }
}
